<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="format-detection" content="telephone=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="icon" href="/assets/logo.png?v=2.0.0" type="image/png" sizes="16x16"><link rel="icon" href="/assets/logo.png?v=2.0.0" type="image/png" sizes="32x32"><meta name="description" content="使用numpy实现逻辑回归对IRIS数据集二分类，使用对数似然损失(Log-likelihood Loss)，并显示训练后loss变化曲线。 知识储备如下：  逻辑回归Logistic Regression 对数似然损失 IRIS数据集介绍 np.concatenate使用">
<meta property="og:type" content="article">
<meta property="og:title" content="使用numpy实现逻辑回归对IRIS数据集二分类">
<meta property="og:url" content="https://wxler.gitee.io/2020/07/16/useNumpy-LogisticRegression-Classify-IRIS/index.html">
<meta property="og:site_name" content="Lei&#39;s Blog">
<meta property="og:description" content="使用numpy实现逻辑回归对IRIS数据集二分类，使用对数似然损失(Log-likelihood Loss)，并显示训练后loss变化曲线。 知识储备如下：  逻辑回归Logistic Regression 对数似然损失 IRIS数据集介绍 np.concatenate使用">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716170728.png">
<meta property="og:image" content="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171020.png">
<meta property="og:image" content="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171106.png">
<meta property="og:image" content="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171124.png">
<meta property="article:published_time" content="2020-07-16T09:59:00.000Z">
<meta property="article:modified_time" content="2020-07-16T09:20:38.992Z">
<meta property="article:author" content="wxl">
<meta property="article:tag" content="numpy">
<meta property="article:tag" content="逻辑回归">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716170728.png"><meta name="keywords" content="wxl, Lei's Blog"><meta name="description" content="博客，分享，开源，心得"><title>使用numpy实现逻辑回归对IRIS数据集二分类 | Lei's Blog</title><link ref="canonical" href="https://wxler.gitee.io/2020/07/16/useNumpy-LogisticRegression-Classify-IRIS/"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.12.1/css/all.min.css" type="text/css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/social-share.js@1.0.16/dist/css/share.min.css" type="text/css"><link rel="stylesheet" href="/css/index.css?v=2.0.0"><link rel="dns-prefetch" href="https://hm.baidu.com"><script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement('script');
  hm.src = 'https://hm.baidu.com/hm.js?01911aa0fc6bdb840626994292397110';
  hm.async = true;

  if (true) {
    hm.setAttribute('data-pjax', '');
  }
  var s = document.getElementsByTagName('script')[0]; 
  s.parentNode.insertBefore(hm, s);
})();</script><script>var Stun = window.Stun || {};
var CONFIG = {
  root: '/',
  algolia: undefined,
  fontIcon: {"prompt":{"success":"fas fa-check-circle","info":"fas fa-arrow-circle-right","warning":"fas fa-exclamation-circle","error":"fas fa-times-circle"},"copyBtn":"fas fa-copy"},
  sidebar: {"offsetTop":"20px","tocMaxDepth":6},
  header: {"enable":true,"showOnPost":true,"scrollDownIcon":true},
  postWidget: {"endText":true},
  nightMode: {"enable":true},
  back2top: {"enable":true},
  codeblock: {"style":"default","highlight":"ocean","wordWrap":false},
  reward: false,
  fancybox: false,
  zoomImage: {"gapAside":"20px"},
  galleryWaterfall: undefined,
  lazyload: true,
  pjax: {"avoidBanner":true},
  externalLink: {"icon":{"enable":true,"name":"fas fa-external-link-alt"}},
  shortcuts: undefined,
  prompt: {"copyButton":"复制","copySuccess":"复制成功","copyError":"复制失败"},
  sourcePath: {"js":"js","css":"css","images":"images"},
};

window.CONFIG = CONFIG;</script><meta name="generator" content="Hexo 4.2.1"></head><body><div class="container" id="container"><header class="header" id="header"><div class="header-inner"><nav class="header-nav header-nav--fixed"><div class="header-nav-inner"><div class="header-nav-menubtn"><i class="fas fa-bars"></i></div><div class="header-nav-menu"><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/"><span class="header-nav-menu-item__icon"><i class="fas fa-home"></i></span><span class="header-nav-menu-item__text">首页</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/archives/"><span class="header-nav-menu-item__icon"><i class="fas fa-folder-open"></i></span><span class="header-nav-menu-item__text">归档</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/categories/"><span class="header-nav-menu-item__icon"><i class="fas fa-layer-group"></i></span><span class="header-nav-menu-item__text">分类</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/tags/"><span class="header-nav-menu-item__icon"><i class="fas fa-tags"></i></span><span class="header-nav-menu-item__text">标签</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/message/"><span class="header-nav-menu-item__icon"><i class="fa fa-comment"></i></span><span class="header-nav-menu-item__text">留言板</span></a></div><div class="header-nav-menu-item"><a class="header-nav-menu-item__link" href="/about/"><span class="header-nav-menu-item__icon"><i class="fas fa-user"></i></span><span class="header-nav-menu-item__text">关于</span></a></div></div><div class="header-nav-search"><span class="header-nav-search__icon"><i class="fas fa-search"></i></span><span class="header-nav-search__text">搜索</span></div><div class="header-nav-mode"><div class="mode"><div class="mode-track"><span class="mode-track-moon"></span><span class="mode-track-sun"></span></div><div class="mode-thumb"></div></div></div></div></nav><div class="header-banner"><div class="header-banner-info"><div class="header-banner-info__title">Lei's Blog</div><div class="header-banner-info__subtitle">一个爱好coding的男孩纸</div></div><div class="header-banner-arrow"><div class="header-banner-arrow__icon"><i class="fas fa-angle-down"></i></div></div></div></div></header><main class="main" id="main"><div class="main-inner"><div class="content-wrap" id="content-wrap"><div class="content" id="content"><!-- Just used to judge whether it is an article page--><div id="is-post"></div><div class="post"><header class="post-header"><h1 class="post-title">使用numpy实现逻辑回归对IRIS数据集二分类</h1><div class="post-meta"><span class="post-meta-item post-meta-item--createtime"><span class="post-meta-item__icon"><i class="far fa-calendar-plus"></i></span><span class="post-meta-item__info">发表于</span><span class="post-meta-item__value">2020-07-16</span></span><span class="post-meta-item post-meta-item--updatetime"><span class="post-meta-item__icon"><i class="far fa-calendar-check"></i></span><span class="post-meta-item__info">更新于</span><span class="post-meta-item__value">2020-07-16</span></span><span class="post-meta-item post-meta-item--wordcount"><span class="post-meta-item__icon"><i class="far fa-file-word"></i></span><span class="post-meta-item__info">字数统计</span><span class="post-meta-item__value">1.3k</span></span><span class="post-meta-item post-meta-item--readtime"><span class="post-meta-item__icon"><i class="far fa-clock"></i></span><span class="post-meta-item__info">阅读时长</span><span class="post-meta-item__value">12分</span></span></div></header><div class="post-body"><p>使用numpy实现逻辑回归对IRIS数据集二分类，使用对数似然损失(Log-likelihood Loss)，并显示训练后loss变化曲线。</p>
<p>知识储备如下：</p>
<ul>
<li>逻辑回归Logistic Regression</li>
<li>对数似然损失</li>
<li>IRIS数据集介绍</li>
<li>np.concatenate使用</li>
</ul>
<a id="more"></a>

        <h2 id="知识储备"   >
          <a href="#知识储备" class="heading-link"><i class="fas fa-link"></i></a>知识储备</h2>
      

        <h3 id="逻辑回归logistic-regression"   >
          <a href="#逻辑回归logistic-regression" class="heading-link"><i class="fas fa-link"></i></a>逻辑回归Logistic Regression</h3>
      
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>y</mi><mo>=</mo><mfrac><mn>1</mn><mrow><mn>1</mn><mo>+</mo><msup><mi>e</mi><mrow><mo>−</mo><mo stretchy="false">(</mo><mi>w</mi><mi>x</mi><mo>+</mo><mi>b</mi><mo stretchy="false">)</mo></mrow></msup></mrow></mfrac></mrow><annotation encoding="application/x-tex">y = \frac{1}{1+e^{-(wx+b)}}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.10877em;vertical-align:-0.78733em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.32144em;"><span style="top:-2.2960000000000003em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathdefault">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.814em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mopen mtight">(</span><span class="mord mathdefault mtight" style="margin-right:0.02691em;">w</span><span class="mord mathdefault mtight">x</span><span class="mbin mtight">+</span><span class="mord mathdefault mtight">b</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.78733em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p>
<p>名字虽然叫回归，但是一般处理的是分类问题，尤其是二分类，比如垃圾邮件的识别，推荐系统，医疗判断等，因为其逻辑与实现简单，在工业界有着广泛的应用。</p>
<p><strong>优点</strong>：</p>
<ul>
<li>实现简单，计算代价不高，易于理解和实现, 广泛的应用于工业问题上；</li>
<li>分类时计算量非常小，速度很快，存储资源低；</li>
</ul>
<p><strong>缺点</strong>：</p>
<ul>
<li>容易欠拟合，当特征空间很大时，逻辑回归的性能不是很好；</li>
<li>不能很好地处理大量多类特征或变量；</li>
</ul>

        <h3 id="对数似然损失"   >
          <a href="#对数似然损失" class="heading-link"><i class="fas fa-link"></i></a>对数似然损失</h3>
      
<p>对数损失, 即对数似然损失(Log-likelihood Loss), 也称逻辑斯特回归损失(Logistic Loss)或交叉熵损失(cross-entropy Loss), 是在概率估计上定义的。它常用于(multi-nominal, 多项)逻辑斯特回归和神经网络,以及一些期望极大算法的变体,可用于评估分类器的概率输出。可参考<span class="exturl"><a class="exturl__link"   href="https://www.cnblogs.com/klchang/p/9217551.html"  target="_blank" rel="noopener">对数损失函数(Logarithmic Loss Function)的原理和 Python 实现</a><span class="exturl__icon"><i class="fas fa-external-link-alt"></i></span></span>了解详情</p>
<p>
        <img   class="lazyload lazyload-gif"
          src="/images/loading.svg" data-src="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716170728.png"  alt="" />
      </p>
<p>损失函数:</p>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>L</mi><mo>=</mo><mfrac><mn>1</mn><mi>m</mi></mfrac><mo>∗</mo><munderover><mo>∑</mo><mi>i</mi><mi>m</mi></munderover><mo>−</mo><msub><mi>y</mi><mi>i</mi></msub><mi>l</mi><mi>o</mi><mi>g</mi><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>−</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><msub><mi>y</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mi>l</mi><mi>o</mi><mi>g</mi><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>f</mi><mo stretchy="false">(</mo><msub><mi>x</mi><mi>i</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">L=\frac{1}{m}*\sum_i^m -y_ilog(f(x_i))-(1-y_i)log(1-f(x_i))
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault">L</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.00744em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.32144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathdefault">m</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:2.929066em;vertical-align:-1.277669em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6513970000000002em;"><span style="top:-1.872331em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span><span style="top:-3.050005em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3000050000000005em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.277669em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">−</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathdefault" style="margin-right:0.01968em;">l</span><span class="mord mathdefault">o</span><span class="mord mathdefault" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord mathdefault" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord mathdefault" style="margin-right:0.01968em;">l</span><span class="mord mathdefault">o</span><span class="mord mathdefault" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord"><span class="mord mathdefault">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.31166399999999994em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mclose">)</span></span></span></span></span></p>
<p>梯度计算：</p>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mfrac><mrow><mi mathvariant="normal">∂</mi><mi>L</mi></mrow><mrow><mi mathvariant="normal">∂</mi><mi>w</mi></mrow></mfrac><mo>=</mo><mfrac><mn>1</mn><mi>m</mi></mfrac><msup><mi>X</mi><mi>T</mi></msup><mo>∗</mo><mo stretchy="false">(</mo><mi>f</mi><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo><mo>−</mo><mi>y</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\frac{\partial L}{\partial w} = \frac{1}{m}X^T*(f(x)-y)
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.05744em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.37144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathdefault" style="margin-right:0.02691em;">w</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathdefault">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.00744em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.32144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathdefault">m</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913309999999999em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathdefault" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathdefault">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></p>
<p>权重更新：</p>
<p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>w</mi><mo>=</mo><mi>w</mi><mo>−</mo><mi>α</mi><mfrac><mrow><mi mathvariant="normal">∂</mi><mi>L</mi></mrow><mrow><mi mathvariant="normal">∂</mi><mi>w</mi></mrow></mfrac></mrow><annotation encoding="application/x-tex">w = w -\alpha\frac{\partial L}{\partial w}
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.02691em;">w</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.66666em;vertical-align:-0.08333em;"></span><span class="mord mathdefault" style="margin-right:0.02691em;">w</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:2.05744em;vertical-align:-0.686em;"></span><span class="mord mathdefault" style="margin-right:0.0037em;">α</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.37144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathdefault" style="margin-right:0.02691em;">w</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathdefault">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p>

        <h3 id="iris数据集介绍"   >
          <a href="#iris数据集介绍" class="heading-link"><i class="fas fa-link"></i></a>IRIS数据集介绍</h3>
      
<p>该数据集包含4个特征变量，1个类别变量。iris每个样本都包含了4个特征：花萼长度，花萼宽度，花瓣长度，花瓣宽度，以及1个类别变量（label）。详情见<a href="#%E5%8A%A0%E8%BD%BD%E6%95%B0%E6%8D%AE">加载数据</a></p>

        <h3 id="npconcatenate使用"   >
          <a href="#npconcatenate使用" class="heading-link"><i class="fas fa-link"></i></a>np.concatenate使用</h3>
      
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">a = np.array([[<span class="number">1</span>, <span class="number">2</span>],[<span class="number">3</span>, <span class="number">4</span>]])</span><br><span class="line">b = np.array([[<span class="number">5</span>, <span class="number">6</span>]])</span><br><span class="line">np.concatenate((a, b), axis = <span class="number">0</span>)</span><br></pre></td></tr></table></div></figure>
<pre><code>array([[1, 2],
       [3, 4],
       [5, 6]])
</code></pre>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">np.concatenate((a, b.T), axis = <span class="number">1</span>)</span><br></pre></td></tr></table></div></figure>
<pre><code>array([[1, 2, 5],
       [3, 4, 6]])
</code></pre>

        <h2 id="加载数据"   >
          <a href="#加载数据" class="heading-link"><i class="fas fa-link"></i></a>加载数据</h2>
      
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> matplotlib.pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"><span class="keyword">from</span> sklearn.datasets <span class="keyword">import</span> load_iris</span><br><span class="line">%matplotlib inline</span><br></pre></td></tr></table></div></figure>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">dataset = load_iris()</span><br><span class="line">inputs = dataset[<span class="string">'data'</span>]</span><br><span class="line">target = dataset[<span class="string">'target'</span>]</span><br><span class="line">print(<span class="string">'inputs.shape:'</span>, inputs.shape)</span><br><span class="line">print(<span class="string">'target.shape:'</span>, target.shape)</span><br><span class="line"><span class="comment"># 三个类别</span></span><br><span class="line">print(<span class="string">'labels:'</span>, set(target))</span><br></pre></td></tr></table></div></figure>
<pre><code>inputs.shape: (150, 4)
target.shape: (150,)
labels: {0, 1, 2}
</code></pre>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">target</span><br></pre></td></tr></table></div></figure>
<pre><code>array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])
</code></pre>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">values = [np.sum(target == <span class="number">0</span>), np.sum(target == <span class="number">1</span>), np.sum(target == <span class="number">2</span>)]</span><br><span class="line">plt.pie(values,labels=[<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>], autopct = <span class="string">'%.1f%%'</span>)</span><br><span class="line">plt.show()</span><br></pre></td></tr></table></div></figure>
<p>
        <img   class="lazyload lazyload-gif"
          src="/images/loading.svg" data-src="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171020.png"  alt="" />
      </p>
<p>关于参数train_test_split的<code>random_state</code>的解释：</p>
<blockquote>
<p>Controls the shuffling applied to the data before applying the split. Pass an int for reproducible output across multiple function calls.<br />
random_state即随机数种子，<strong>目的是为了保证程序每次运行都分割一样的训练集和测试集。否则，同样的算法模型在不同的训练集和测试集上的效果不一样。</strong></p>
</blockquote>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> sklearn.model_selection <span class="keyword">import</span> train_test_split</span><br><span class="line"><span class="comment"># 只取前两类， 做二分类</span></span><br><span class="line">two_class_input = inputs[:<span class="number">100</span>]</span><br><span class="line">two_class_target = target[:<span class="number">100</span>]</span><br><span class="line">x_train, x_test, y_train, y_test = train_test_split(</span><br><span class="line">                    two_class_input,two_class_target,</span><br><span class="line">                    test_size = <span class="number">0.3</span>,</span><br><span class="line">                    random_state = <span class="number">0</span>)</span><br><span class="line">y_train = y_train.reshape(<span class="number">-1</span>,<span class="number">1</span>)</span><br><span class="line">y_test = y_test.reshape(<span class="number">-1</span>,<span class="number">1</span>)</span><br><span class="line">print(x_train.shape, x_test.shape, y_train.shape, y_test.shape)</span><br></pre></td></tr></table></div></figure>
<pre><code>(70, 4) (30, 4) (70, 1) (30, 1)
</code></pre>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># add one feature to x</span></span><br><span class="line">x_train = np.concatenate([x_train, np.ones((x_train.shape[<span class="number">0</span>], <span class="number">1</span>))], axis = <span class="number">1</span>)</span><br><span class="line">x_test = np.concatenate([x_test, np.ones((x_test.shape[<span class="number">0</span>], <span class="number">1</span>))], axis = <span class="number">1</span>)</span><br><span class="line">print(x_train.shape, x_test.shape)</span><br></pre></td></tr></table></div></figure>
<pre><code>(70, 5) (30, 5)
</code></pre>

        <h2 id="定义模型"   >
          <a href="#定义模型" class="heading-link"><i class="fas fa-link"></i></a>定义模型</h2>
      
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">sigmoid</span><span class="params">(x)</span>:</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">1</span> / (<span class="number">1</span> + np.exp(-x))</span><br><span class="line">x = np.arange(<span class="number">-10</span>, <span class="number">10</span>, step = <span class="number">0.1</span>)</span><br><span class="line">fig, ax = plt.subplots(figsize = (<span class="number">8</span>, <span class="number">4</span>))</span><br><span class="line">ax.plot(x, sigmoid(x), c = <span class="string">'green'</span>)</span><br></pre></td></tr></table></div></figure>
<pre><code>[&lt;matplotlib.lines.Line2D at 0x28f77053348&gt;]
</code></pre>
<p>
        <img   class="lazyload lazyload-gif"
          src="/images/loading.svg" data-src="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171106.png"  alt="" />
      </p>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">compute_loss = <span class="keyword">lambda</span> pred_y, y: np.mean(-y * np.log(pred_y)-(<span class="number">1</span>-y) * np.log(<span class="number">1</span>-pred_y))</span><br><span class="line"><span class="comment"># weight and bias init</span></span><br><span class="line">w = np.random.randn(<span class="number">5</span>, <span class="number">1</span>)</span><br><span class="line"><span class="comment"># 上一个loss</span></span><br><span class="line">losses = []</span><br><span class="line">last_loss = <span class="number">10000</span></span><br><span class="line">pred_y =sigmoid(np.dot(x_train, w))</span><br><span class="line"><span class="comment"># 当前loss</span></span><br><span class="line">now_loss = compute_loss(pred_y, y_train)</span><br><span class="line">i = <span class="number">0</span></span><br><span class="line"><span class="keyword">while</span> abs(now_loss - last_loss)&gt;<span class="number">1e-4</span>:</span><br><span class="line">    last_loss = now_loss</span><br><span class="line">    i = i + <span class="number">1</span></span><br><span class="line">    <span class="comment"># 计算梯度</span></span><br><span class="line">    grad = x_train.T.dot((pred_y - y_train)) / len(y_train)</span><br><span class="line">    <span class="comment"># 更新梯度</span></span><br><span class="line">    w = w - <span class="number">0.001</span> * grad</span><br><span class="line">    </span><br><span class="line">    <span class="comment"># 前导计算</span></span><br><span class="line">    pred_y = sigmoid(np.dot(x_train, w))</span><br><span class="line">    now_loss = compute_loss(pred_y, y_train)</span><br><span class="line">    losses.append(now_loss)</span><br><span class="line">fig, ax = plt.subplots(figsize = (<span class="number">10</span>, <span class="number">4</span>))</span><br><span class="line">ax.plot(np.arange(len(losses)), losses, c = <span class="string">'r'</span>)</span><br></pre></td></tr></table></div></figure>
<pre><code>[&lt;matplotlib.lines.Line2D at 0x28f77053508&gt;]
</code></pre>
<p>
        <img   class="lazyload lazyload-gif"
          src="/images/loading.svg" data-src="https://gitee.com/wxler/blogimg/raw/master/imgs/20200716171124.png"  alt="" />
      </p>

        <h2 id="测试样例"   >
          <a href="#测试样例" class="heading-link"><i class="fas fa-link"></i></a>测试样例</h2>
      
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 测试</span></span><br><span class="line">test_pred = sigmoid(np.dot(x_test, w))</span><br><span class="line">pre_test_y = np.array(test_pred &gt; <span class="number">0.5</span>, dtype = np.float32)</span><br><span class="line">acc = np.sum(pre_test_y == y_test) / len(y_test)</span><br><span class="line">print(<span class="string">"the accary of model is &#123;&#125;"</span>.format(acc*<span class="number">100</span>))</span><br></pre></td></tr></table></div></figure>
<pre><code>the accary of model is 100.0
</code></pre>
<figure class="highlight python"><div class="table-container"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">print(pre_test_y.reshape(<span class="number">1</span>,<span class="number">-1</span>))</span><br><span class="line">print(y_test.reshape(<span class="number">1</span>,<span class="number">-1</span>))</span><br></pre></td></tr></table></div></figure>
<p><code>[[0. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 1. 0. 0. 0. 1. 1. 1.]]</code><br />
<code>[[0 1 0 1 1 1 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 1 1]]</code></p>
</div><footer class="post-footer"><div class="post-ending ending"><div class="ending__text">------ 本文结束，感谢您的阅读 ------</div></div><div class="post-copyright copyright"><div class="copyright-author"><span class="copyright-author__name">本文作者: </span><span class="copyright-author__value"><a href="https://wxler.gitee.io">wxl</a></span></div><div class="copyright-link"><span class="copyright-link__name">本文链接: </span><span class="copyright-link__value"><a href="https://wxler.gitee.io/2020/07/16/useNumpy-LogisticRegression-Classify-IRIS/">https://wxler.gitee.io/2020/07/16/useNumpy-LogisticRegression-Classify-IRIS/</a></span></div><div class="copyright-notice"><span class="copyright-notice__name">版权声明: </span><span class="copyright-notice__value">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en" rel="external nofollow" target="_blank">BY-NC-SA</a> 许可协议。转载请注明出处！</span></div></div><div class="post-tags"><span class="post-tags-item"><span class="post-tags-item__icon"><i class="fas fa-tag"></i></span><a class="post-tags-item__link" href="https://wxler.gitee.io/tags/numpy/">numpy</a></span><span class="post-tags-item"><span class="post-tags-item__icon"><i class="fas fa-tag"></i></span><a class="post-tags-item__link" href="https://wxler.gitee.io/tags/%E9%80%BB%E8%BE%91%E5%9B%9E%E5%BD%92/">逻辑回归</a></span></div><div class="post-share"><div class="social-share" data-sites="qzone, qq, weibo, wechat, douban, linkedin, facebook, twitter, google">分享到：</div></div><nav class="post-paginator paginator"><div class="paginator-prev"><a class="paginator-prev__link" href="/2020/07/18/google-colab-mount-drive%20/"><span class="paginator-prev__icon"><i class="fas fa-angle-left"></i></span><span class="paginator-prev__text">Google Colab挂载drive上的数据文件</span></a></div><div class="paginator-next"><a class="paginator-next__link" href="/2020/07/16/useNumpy-Linear-Predict-boston/"><span class="paginator-prev__text">使用numpy实现线性模型预测boston房价</span><span class="paginator-next__icon"><i class="fas fa-angle-right"></i></span></a></div></nav></footer></div></div><div class="comments" id="comments"><div id="valine-container"></div></div></div><div class="sidebar-wrap" id="sidebar-wrap"><aside class="sidebar" id="sidebar"><div class="sidebar-nav"><span class="sidebar-nav-toc current">文章目录</span><span class="sidebar-nav-ov">站点概览</span></div><section class="sidebar-toc"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#知识储备"><span class="toc-number">1.</span> <span class="toc-text">
          知识储备</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#逻辑回归logistic-regression"><span class="toc-number">1.1.</span> <span class="toc-text">
          逻辑回归Logistic Regression</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#对数似然损失"><span class="toc-number">1.2.</span> <span class="toc-text">
          对数似然损失</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#iris数据集介绍"><span class="toc-number">1.3.</span> <span class="toc-text">
          IRIS数据集介绍</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#npconcatenate使用"><span class="toc-number">1.4.</span> <span class="toc-text">
          np.concatenate使用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#加载数据"><span class="toc-number">2.</span> <span class="toc-text">
          加载数据</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#定义模型"><span class="toc-number">3.</span> <span class="toc-text">
          定义模型</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#测试样例"><span class="toc-number">4.</span> <span class="toc-text">
          测试样例</span></a></li></ol></section><!-- ov = overview--><section class="sidebar-ov hide"><div class="sidebar-ov-author"><div class="sidebar-ov-author__avatar"><img class="sidebar-ov-author__avatar_img" src="/assets/myhexo.jpg" alt="avatar"></div><p class="sidebar-ov-author__text">A lifetime of AI</p></div><div class="sidebar-ov-social"><a class="sidebar-ov-social-item" href="https://github.com/wxler" target="_blank" rel="noopener" data-popover="Github" data-popover-pos="up"><span class="sidebar-ov-social-item__icon"><i class="fab fa-github"></i></span></a><a class="sidebar-ov-social-item" href="mailto:wangxiaolei1516@qq.com" target="_blank" rel="noopener" data-popover="邮箱" data-popover-pos="up"><span class="sidebar-ov-social-item__icon"><i class="fa fa-envelope"></i></span></a></div><div class="sidebar-ov-state"><a class="sidebar-ov-state-item sidebar-ov-state-item--posts" href="/archives/"><div class="sidebar-ov-state-item__count">10</div><div class="sidebar-ov-state-item__name">归档</div></a><a class="sidebar-ov-state-item sidebar-ov-state-item--categories" href="/categories/"><div class="sidebar-ov-state-item__count">6</div><div class="sidebar-ov-state-item__name">分类</div></a><a class="sidebar-ov-state-item sidebar-ov-state-item--tags" href="/tags/"><div class="sidebar-ov-state-item__count">11</div><div class="sidebar-ov-state-item__name">标签</div></a></div><div class="sidebar-ov-cc"><a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en" target="_blank" rel="noopener" data-popover="知识共享许可协议" data-popover-pos="up"><img src="/images/cc-by-nc-sa.svg"></a></div></section></aside></div><div class="clearfix"></div></div></main><footer class="footer" id="footer"><div class="footer-inner"><div><span>Copyright © 2020</span><span class="footer__icon"><i class="fas fa-heart"></i></span><span>wxler. All Rights Reserved.</span></div><div><span>由 <a href="http://hexo.io/" title="Hexo" target="_blank" rel="noopener">Hexo</a> 强力驱动</span><span> v4.2.1</span><span class="footer__devider">|</span><span>主题 - <a href="https://github.com/liuyib/hexo-theme-stun/" title="Stun" target="_blank" rel="noopener">Stun</a></span><span> v2.0.0</span></div><div>托管于 <a href="https://github.com/wxler/" rel="noopener" target="_blank">Github</a></div></div></footer><div class="loading-bar" id="loading-bar"><div class="loading-bar__progress"></div></div><div class="back2top" id="back2top"><span class="back2top__icon"><i class="fas fa-rocket"></i></span></div></div><div class="search-mask"></div><div class="search-popup"><span class="search-close"></span><div class="search-input"><input placeholder="搜索文章（支持多关键词，请用空格分隔）"></div><div class="search-results"></div></div><script src="https://cdn.jsdelivr.net/npm/jquery@v3.4.1/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@1.5.2/velocity.ui.min.js"></script><script src="https://cdn.jsdelivr.net/npm/ribbon.js@latest/dist/ribbon.min.js" size="120" alpha="0.6" zIndex="-1"></script><script src="https://cdn.jsdelivr.net/npm/lazyload@2.0.0-rc.2/lazyload.min.js"></script><script src="https://cdn.jsdelivr.net/npm/social-share.js@1.0.16/dist/js/social-share.min.js"></script><script>function initSearch() {
  var isXML = true;
  var search_path = 'search.json';

  if (!search_path) {
    search_path = 'search.xml';
  } else if (/json$/i.test(search_path)) {
    isXML = false;
  }

  var path = '/' + search_path;
  $.ajax({
    url: path,
    dataType: isXML ? 'xml' : 'json',
    async: true,
    success: function (res) {
      var datas = isXML ? $('entry', res).map(function () {
        // 将 XML 转为 JSON
        return {
          title: $('title', this).text(),
          content: $('content', this).text(),
          url: $('url', this).text()
        };
      }).get() : res;
      var $input = $('.search-input input');
      var $result = $('.search-results');
      // 搜索对象（标题、内容）的权重，影响显示顺序
      var WEIGHT = { title: 100, content: 1 };
      var searchPost = function () {
        var searchText = $input.val().toLowerCase().trim();
        // 根据空白字符分隔关键字
        var keywords = searchText.split(/[\s]+/);
        // 搜索结果
        var matchPosts = [];

        // 有多个关键字时，将原文字整个保存下来
        if (keywords.length > 1) {
          keywords.push(searchText);
        }
        // 防止未输入字符时搜索
        if (searchText.length > 0) {
          datas.forEach(function (data) {
            var isMatch  = false;
            // 没有标题的文章使用预设的 i18n 变量代替
            var title = (data.title && data.title.trim()) || '[ 文章无标题 ]';
            var titleLower = title && title.toLowerCase();
            // 删除 HTML 标签 和 所有空白字符
            var content = data.content && data.content.replace(/<[^>]+>/g, '');
            var contentLower = content && content.toLowerCase();
            // 删除重复的 /
            var postURL = data.url && decodeURI(data.url).replace(/\/{2,}/g, '/');
            // 标题中匹配到的关键词
            var titleHitSlice = [];
            // 内容中匹配到的关键词
            var contentHitSlice = [];

            keywords.forEach(function (keyword) {
              /**
              * 获取匹配的关键词的索引
              * @param {String} keyword 要匹配的关键字
              * @param {String} text 原文字
              * @param {Boolean} caseSensitive 是否区分大小写
              * @param {Number} weight 匹配对象的权重。权重大的优先显示
              * @return {Array}
              */
              function getIndexByword (word, text, caseSensitive, weight) {
                if (!word || !text) {
                  return [];
                };

                var startIndex = 0; // 每次匹配的开始索引
                var index = -1;     // 匹配到的索引值
                var result = [];    // 匹配结果

                if (!caseSensitive) {
                  word = word.toLowerCase();
                  text = text.toLowerCase();
                }

                while((index = text.indexOf(word, startIndex)) !== -1) {
                  var hasMatch = false;
                  // 索引位置相同的关键词，保留长度较长的
                  titleHitSlice.forEach(function (hit) {
                    if (hit.index === index && hit.word.length < word.length) {
                      hit.word = word;
                      hasMatch = true;
                    }
                  });
                  startIndex = index + word.length;
                  !hasMatch && result.push({ index: index, word: word, weight: weight });
                }
                return result;
              }
              titleHitSlice = titleHitSlice.concat(getIndexByword(keyword, titleLower, false, WEIGHT.title));
              contentHitSlice = contentHitSlice.concat(getIndexByword(keyword, contentLower, false, WEIGHT.content));
            });

            var hitTitle = titleHitSlice.length;
            var hitContent = contentHitSlice.length;

            if (hitTitle > 0 || hitContent > 0) {
              isMatch = true;
            }
            if (isMatch) {
              ;[titleHitSlice, contentHitSlice].forEach(function (hit) {
                // 按照匹配文字的索引的递增顺序排序
                hit.sort(function (left, right) {
                  return left.index - right.index;
                });
              });
              /**
              * 给文本中匹配到的关键词添加标记，从而进行高亮显示
              * @param {String} text 原文本
              * @param {Array} hitSlice 匹配项的索引信息
              * @param {Number} start 开始索引
              * @param {Number} end 结束索引
              * @return {String}
              */
              function highlightKeyword (text, hitSlice, start, end) {
                if (!text || !hitSlice || !hitSlice.length) {
                  return;
                }

                var result = '';
                var startIndex = start;
                var endIndex = end;
                hitSlice.forEach(function (hit) {
                  if (hit.index < startIndex) {
                    return;
                  }

                  var hitWordEnd = hit.index + hit.word.length;
                  result += text.slice(startIndex, hit.index);
                  result += '<b>' + text.slice(hit.index, hitWordEnd) + '</b>';
                  startIndex = hitWordEnd;
                });
                result += text.slice(startIndex, endIndex);
                return result;
              }

              var postData = {};
              // 文章总的搜索权重
              var postWeight = titleHitSlice.length * WEIGHT.title + contentHitSlice.length * WEIGHT.content;
              // 标记匹配关键词后的标题
              var postTitle = highlightKeyword(title, titleHitSlice, 0, title.length) || title;
              // 标记匹配关键词后的内容
              var postContent;
              // 显示内容的长度
              var SHOW_WORD_LENGTH = 200;
              // 命中关键词前的字符显示长度
              var SHOW_WORD_FRONT_LENGTH = 20;
              var SHOW_WORD_END_LENGTH = SHOW_WORD_LENGTH - SHOW_WORD_FRONT_LENGTH;

              // 截取匹配的第一个字符，前后共 200 个字符来显示
              if (contentHitSlice.length > 0) {
                var firstIndex = contentHitSlice[0].index;
                var start = firstIndex > SHOW_WORD_FRONT_LENGTH ? firstIndex - SHOW_WORD_FRONT_LENGTH : 0;
                var end = firstIndex + SHOW_WORD_END_LENGTH;
                postContent = highlightKeyword(content, contentHitSlice, start, end);
              } else { // 未匹配到内容，直接截取前 200 个字符来显示
                postContent = content.slice(0, SHOW_WORD_LENGTH);
              }
              postData.title = postTitle;
              postData.content = postContent;
              postData.url = postURL;
              postData.weight = postWeight;
              matchPosts.push(postData);
            }
          });
        }

        var resultInnerHtml = '';
        if (matchPosts.length) {
          // 按权重递增的顺序排序，使权重大的优先显示
          matchPosts.sort(function (left, right) {
            return right.weight - left.weight;
          });
          resultInnerHtml += '<ul>';
          matchPosts.forEach(function (post) {
            resultInnerHtml += '<li><a class="search-results-title" href="' + post.url + '">';
            resultInnerHtml += post.title;
            resultInnerHtml += '</a><div class="search-results-content">';
            resultInnerHtml += post.content;
            resultInnerHtml += '</div></li>';
          });
          resultInnerHtml += '</ul>';
        } else {
          resultInnerHtml += '<div class="search-results-none"><i class="far fa-meh"></i></div>';
        }
        $result.html(resultInnerHtml);
      };
      $input.on('input', searchPost);
      $input.on('keyup', function (e) {
        if (e.keyCode === Stun.utils.codeToKeyCode('Enter')) {
          searchPost();
        }
      });
    }
  });
}

function closeSearch () {
  $('body').css({ overflow: 'auto' });
  $('.search-popup').css({ display: 'none' });
  $('.search-mask').css({ display: 'none' });
}

window.addEventListener('DOMContentLoaded', function () {
  Stun.utils.pjaxReloadLocalSearch = function () {
    $('.header-nav-search').on('click', function (e) {
      e.stopPropagation();
      $('body').css('overflow', 'hidden');
      $('.search-popup')
        .velocity('stop')
        .velocity('transition.expandIn', {
          duration: 300,
          complete: function () {
            $('.search-popup input').focus();
          }
        });
      $('.search-mask')
        .velocity('stop')
        .velocity('transition.fadeIn', {
          duration: 300
        });

      initSearch();
    });
    $('.search-mask, .search-close').on('click', function () {
      closeSearch();
    });
    $(document).on('keydown', function (e) {
      // Escape <=> 27
      if (e.keyCode === Stun.utils.codeToKeyCode('Escape')) {
        closeSearch();
      }
    });
  };

  Stun.utils.pjaxReloadLocalSearch();
}, false);</script><script src="https://cdn.jsdelivr.net/npm/pjax@latest/pjax.min.js"></script><script>window.addEventListener('DOMContentLoaded', function () {
  var pjax = new Pjax({"selectors":["head title","#main",".pjax-reload"],"history":true,"scrollTo":false,"scrollRestoration":false,"cacheBust":false,"debug":false,"currentUrlFullReload":false,"timeout":0});
  // 加载进度条的计时器
  var loadingTimer = null;

  // 重置页面 Y 方向上的滚动偏移量
  document.addEventListener('pjax:send', function () {
    $('.header-nav-menu').removeClass('show');
    if (CONFIG.pjax && CONFIG.pjax.avoidBanner) {
      $('html').velocity('scroll', {
        duration: 500,
        offset: $('#header').height(),
        easing: 'easeInOutCubic'
      });
    }

    var loadingBarWidth = 20;
    var MAX_LOADING_WIDTH = 95;

    $('.loading-bar').addClass('loading');
    $('.loading-bar__progress').css('width', loadingBarWidth + '%');
    clearInterval(loadingTimer);
    loadingTimer = setInterval(function () {
      loadingBarWidth += 3;
      if (loadingBarWidth > MAX_LOADING_WIDTH) {
        loadingBarWidth = MAX_LOADING_WIDTH;
      }
      $('.loading-bar__progress').css('width', loadingBarWidth + '%');
    }, 500);
  }, false);

  window.addEventListener('pjax:complete', function () {
    clearInterval(loadingTimer);
    $('.loading-bar__progress').css('width', '100%');
    $('.loading-bar').removeClass('loading');
    setTimeout(function () {
      $('.loading-bar__progress').css('width', '0');
    }, 400);
    $('link[rel=prefetch], script[data-pjax-rm]').each(function () {
      $(this).remove();
    });
    $('script[data-pjax], #pjax-reload script').each(function () {
      $(this).parent().append($(this).remove());
    });

    if (Stun.utils.pjaxReloadBoot) {
      Stun.utils.pjaxReloadBoot();
    }
    if (Stun.utils.pjaxReloadScroll) {
      Stun.utils.pjaxReloadScroll();
    }
    if (Stun.utils.pjaxReloadSidebar) {
      Stun.utils.pjaxReloadSidebar();
    }
    if (false) {
      if (Stun.utils.pjaxReloadHeader) {
        Stun.utils.pjaxReloadHeader();
      }
      if (Stun.utils.pjaxReloadScrollIcon) {
        Stun.utils.pjaxReloadScrollIcon();
      }
      if (Stun.utils.pjaxReloadLocalSearch) {
        Stun.utils.pjaxReloadLocalSearch();
      }
    }
  }, false);
}, false);</script><div id="pjax-reload"><link href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/katex.min.css" rel="stylesheet" type="text/css"><link href="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/copy-tex.css" rel="stylesheet" type="text/css"><script src="https://cdn.jsdelivr.net/npm/katex@0.10.2/dist/contrib/copy-tex.min.js"></script></div><script src="https://cdn.jsdelivr.net/npm/leancloud-storage@latest/dist/av-min.js"></script><script src="https://cdn.jsdelivr.net/npm/valine@latest/dist/Valine.min.js"></script><script data-pjax="">function loadValine () {
  var GUEST_INFO = ['nick', 'mail', 'link'];
  var guest_info = 'nick,mail';

  guest_info = guest_info.split(',').filter(function(item) {
    return GUEST_INFO.indexOf(item) > -1;
  });
  new Valine({
    el: '#valine-container',
    appId: 'kBUfBo302Sl5ViCNcWef6wYT-gzGzoHsz',
    appKey: 'hq4rU6YND5ziczBa2PLLUBiM',
    notify: true,
    verify: false,
    placeholder: '有什么需要和我说的，请填写昵称与邮箱(邮箱不会公开显示)，点击评论吧(支持匿名评论)！',
    avatar: 'mp',
    meta: guest_info,
    pageSize: '15' || 10,
    visitor: false,
    recordIP: false,
    lang: '' || 'zh-cn',
    path: window.location.pathname
  });
}

if (true) {
  loadValine();
} else {
  window.addEventListener('DOMContentLoaded', loadValine, false);
}</script><script src="/js/utils.js?v=2.0.0"></script><script src="/js/stun-boot.js?v=2.0.0"></script><script src="/js/scroll.js?v=2.0.0"></script><script src="/js/header.js?v=2.0.0"></script><script src="/js/sidebar.js?v=2.0.0"></script></body></html>